package com.ruoyi.depot.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.ruoyi.commodity.domain.*;
import com.ruoyi.commodity.mapper.*;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.OrdersProduct;
import com.ruoyi.common.core.domain.ProcuredOrders;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.InventoryChangeType;
import com.ruoyi.common.enums.QualityCheckMethod;
import com.ruoyi.common.enums.QualityCheckStatus;
import com.ruoyi.common.enums.StorageTypeEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.depot.domain.*;
import com.ruoyi.depot.domain.vo.QualityInspectionDetailVO;
import com.ruoyi.depot.domain.vo.QualityInspectionVO;
import com.ruoyi.depot.mapper.*;
import com.ruoyi.procured.mapper.ProcuredOrdersMapper;
import com.ruoyi.procured.service.impl.PaymentRequestServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import com.ruoyi.depot.service.IQualityInspectionService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 品检Service业务层处理
 *
 * @author luxiaoyu
 * @date 2024-11-05
 */
@Service
public class QualityInspectionServiceImpl implements IQualityInspectionService {
	@Autowired
	private QualityInspectionMapper qualityInspectionMapper;

	@Autowired
	private QualityInspectionDetailMapper detailMapper;

	@Autowired
	private ReceiptProductsMapper receiptProductsMapper;

	@Autowired
	private ProductCustomQualityItemMapper productCustomQualityItemMapper;

	@Autowired
	private ProductImagesMapper productImagesMapper;

	@Autowired
	private QualityTemplateItemMapper qualityTemplateItemMapper;

	@Autowired
	private ProductMapper productMapper;

	@Autowired
	private ProcuredStorageMapper procuredStorageMapper;

	@Autowired
	private ProcuredStorageDetailMapper procuredStorageDetailMapper;

	@Autowired
	private OrdersProductMapper ordersProductMapper;

	@Autowired
	private ProcuredOrdersMapper procuredOrdersMapper;

	@Autowired
	private LocalInventoryMapper localInventoryMapper;

	@Autowired
	private LocalInventoryDetailsMapper localInventoryDetailsMapper;

	@Autowired
	private ProductImageMapper productImageMapper;

	@Autowired
	private InboundStockMapper inboundStockMapper;

	@Autowired
	private PaymentRequestServiceImpl paymentRequestService;

	@Autowired
	private RedisCache redisCache;

	/**
	 * 查询品检
	 *
	 * @param inspectionId 品检主键
	 * @return 品检
	 */
	@Override
	public QualityInspectionVO selectQualityInspectionByInspectionId(String inspectionId) {
		QualityInspectionVO qualityInspectionVO = qualityInspectionMapper.selectQualityInspectionByInspectionId(inspectionId);
		// —— 1. 合并同 SKU，并把所有 GTIN 收集到 gtinList ——
		List<QualityInspectionDetail> rawDetails = qualityInspectionVO.getInspectionDetails();
		Map<String, QualityInspectionDetail> merged = new LinkedHashMap<>();

		for (QualityInspectionDetail d : rawDetails) {
			String sku = d.getSku();

			// 第一次见到这个 SKU，要先给它初始化 gtinList
			if (!merged.containsKey(sku)) {
				// 初始化被当作合并载体的 d 的 gtinList
				d.setGtins(new ArrayList<>());
				d.getGtins().add(d.getGtin());
				merged.put(sku, d);
			} else {
				QualityInspectionDetail exist = merged.get(sku);
				// 累加 inspectedQuantity 质检量
				exist.setInspectedQuantity(exist.getInspectedQuantity() + d.getInspectedQuantity());
				// 累加次品量
				exist.setDefectiveQuantity(exist.getDefectiveQuantity() + d.getDefectiveQuantity());
				// 累加良品量
				exist.setPassQuantity(exist.getPassQuantity() + d.getPassQuantity());
				// 合并 GTIN 集合（去重）
				if (!exist.getGtins().contains(d.getGtin())) {
					exist.getGtins().add(d.getGtin());
				}
			}
		}
		// 覆盖原 List
		qualityInspectionVO.setInspectionDetails(new ArrayList<>(merged.values()));

		Set<Long> productIds = qualityInspectionVO.getInspectionDetails().stream()
				.map(QualityInspectionDetail::getProductId)
				.collect(Collectors.toSet());

		Map<Long, List<ProductCustomQualityItem>> customItemsMap = preloadCustomQualityItems(productIds);
		Map<Long, Product> productsMap = preloadProducts(productIds);
		Map<Long, List<String>> imagesMap = preloadProductImages(productIds);

		for (QualityInspectionDetail inspectionDetail : qualityInspectionVO.getInspectionDetails()) {
			Long productId = inspectionDetail.getProductId();

			List<ProductCustomQualityItem> list = new ArrayList<>();
			if (customItemsMap.containsKey(productId)) {
				list.addAll(customItemsMap.get(productId));
			}

			if (productsMap.containsKey(productId)) {
				Long templateId = productsMap.get(productId).getTemplateId();
				List<ProductCustomQualityItem> templateItems = loadTemplateItems(templateId);
				list.addAll(templateItems);
			}

			List<String> imagesList = imagesMap.getOrDefault(productId, new ArrayList<>());

			inspectionDetail.setImagesPath(imagesList);
			inspectionDetail.setQualityItems(list);
		}
		return qualityInspectionVO;
	}

	private Map<Long, List<ProductCustomQualityItem>> preloadCustomQualityItems(Set<Long> productIds) {
		return productCustomQualityItemMapper.selectList(new LambdaQueryWrapper<ProductCustomQualityItem>().in(ProductCustomQualityItem::getProductId, productIds)).stream()
				.collect(Collectors.groupingBy(item -> Long.valueOf(item.getProductId())));
	}

	private Map<Long, Product> preloadProducts(Set<Long> productIds) {
		return productMapper.selectProductListById(productIds.toArray(new Long[0])).stream()
				.collect(Collectors.toMap(Product::getId, Function.identity()));
	}

	private Map<Long, List<String>> preloadProductImages(Set<Long> productIds) {
		return productImagesMapper.selectList(new LambdaQueryWrapper<ProductImages>().in(ProductImages::getProductId, productIds)).stream()
				.collect(Collectors.groupingBy(item -> Long.valueOf(item.getProductId()),
						Collectors.mapping(ProductImages::getImagePath, Collectors.toList())));
	}

	private List<ProductCustomQualityItem> loadTemplateItems(Long templateId) {
		return qualityTemplateItemMapper.selectList(new LambdaQueryWrapper<QualityTemplateItem>().eq(QualityTemplateItem::getTemplateId, templateId))
				.stream().map(s -> {
					ProductCustomQualityItem item = new ProductCustomQualityItem();
					item.setInspectionItem(s.getInspectionItem());
					item.setInspectionContent(s.getInspectionContent());
					return item;
				}).collect(Collectors.toList());
	}


//	@Override
//	public QualityInspectionVO selectQualityInspectionByInspectionId(String inspectionId) {
//		QualityInspectionVO qualityInspectionVO = qualityInspectionMapper.selectQualityInspectionByInspectionId(inspectionId);
//		for (QualityInspectionDetail inspectionDetail : qualityInspectionVO.getInspectionDetails()) {
//			Long productId = inspectionDetail.getProductId();
//			List<ProductCustomQualityItem> list = new ArrayList<>();// 用于存储质检项
//			List<String> imagesList = new ArrayList<>();// 用于存储图片路径
//			// 根据产品id查询对应的自定义质检项
//			List<ProductCustomQualityItem> productCustomQualityItems = productCustomQualityItemMapper.selectList(new LambdaQueryWrapper<ProductCustomQualityItem>().eq(ProductCustomQualityItem::getProductId, productId));
//			if(!productCustomQualityItems.isEmpty()){
//				for (ProductCustomQualityItem productCustomQualityItem : productCustomQualityItems) {
//					ProductCustomQualityItem item = new ProductCustomQualityItem();
//					item.setInspectionItem(productCustomQualityItem.getInspectionItem());//质检项
//					item.setInspectionContent(productCustomQualityItem.getInspectionContent());//质检内容
//					list.add(item);
//				}
//			}
//			// 根据产品id查询对应的质检模板id
//			Product product = productMapper.selectProductById(productId);
//			Long templateId = product.getTemplateId();
//			// 根据质检模板id查询出对应的质检数据
//			List<QualityTemplateItem> qualityTemplateItems = qualityTemplateItemMapper.selectList(new LambdaQueryWrapper<QualityTemplateItem>().eq(QualityTemplateItem::getTemplateId, templateId));
//			if(!qualityTemplateItems.isEmpty()){
//				for (QualityTemplateItem qualityTemplateItem : qualityTemplateItems) {
//					ProductCustomQualityItem item = new ProductCustomQualityItem();
//					item.setInspectionItem(qualityTemplateItem.getInspectionItem());//质检项
//					item.setInspectionContent(qualityTemplateItem.getInspectionContent());//质检内容
//					list.add(item);
//				}
//			}
//
//
//			// 根据产品id查询出对应的质检图片
//			List<ProductImages> productImages = productImagesMapper.selectList(new LambdaQueryWrapper<ProductImages>().eq(ProductImages::getProductId, productId));
//			if(!productImages.isEmpty()){
//				for (ProductImages productImage : productImages) {
//					imagesList.add(productImage.getImagePath());
//				}
//			}
//
//			inspectionDetail.setImagesPath(imagesList);
//			inspectionDetail.setQualityItems(list);
//		}
//		return qualityInspectionVO;
//	}

	/**
	 * 查询品检列表
	 *
	 * @param qualityInspection 品检
	 * @return 品检
	 */
	@Override
	public List<QualityInspectionVO> selectQualityInspectionList(QualityInspection qualityInspection) {
		return qualityInspectionMapper.selectQualityInspectionList(qualityInspection);
	}


//	@Transactional
//	@Override
//	public int insertBatchQualityInspection(List<Receipt> qualityInspections) {
//		int countExpected = 0; // 计数器，统计预期插入的记录数
//		int successCount = 0; // 计数器，统计成功插入的记录数
//
//		// 收集所有的收货单id和产品id
//		Set<String> receiptIds = new HashSet<>();
//		Set<Long> productIds = new HashSet<>();
//		for (Receipt qualityInspection : qualityInspections) {
//			for (DTOReceiptProducts qualityInspectionDatum : qualityInspection.getDtoReceiptProductsList()) {
//				receiptIds.add(qualityInspectionDatum.getReceiptId());
//				productIds.add(qualityInspectionDatum.getProductId());
//			}
//		}
//
//		// 一次性查询所有的收货单详细
//		List<ReceiptProducts> productsList = receiptProductsMapper.selectByReceiptIdAndProductIdList(receiptIds, productIds);
//		Map<String, ReceiptProducts> productsMap = productsList.stream()
//				.collect(Collectors.toMap(item -> item.getReceiptId() + item.getProductId() + item.getGtin(), Function.identity()));
//
//		// 用于批量插入质检单的列表
//		List<QualityInspection> inspectionsToInsert = new ArrayList<>();
//		// 用于批量更新的列表
//		List<ReceiptProducts> updatedProducts = new ArrayList<>();
//		// 用于批量插入质检单详情的列表
//		List<QualityInspectionDetail> inspectionDetails = new ArrayList<>();
//
//		// 生成质检单号列表
//		List<String> qualityCodes = generateCode(qualityInspections.size());
//
//		for (int i = 0; i < qualityInspections.size(); i++) {
//			Receipt qualityInspection = qualityInspections.get(i);
//			if (qualityInspection == null || qualityInspection.getDtoReceiptProductsList().isEmpty()) {
//				throw new IllegalArgumentException("质检数据不能为空或为空集合");
//			}
//
//			// 创建质检单
//			Long totalInspectionQuantity = qualityInspection.getDtoReceiptProductsList().stream()
//					.map(DTOReceiptProducts::getReceiptQuantity)
//					.filter(Objects::nonNull)
//					.filter(quantity -> quantity != 0)
//					.reduce(0L, Long::sum);
//
//			QualityInspection inspection = new QualityInspection();
//			inspection.setInspectionId(IdUtils.fastSimpleUUID());
//			inspection.setQualityCode(qualityCodes.get(i)); // 使用预先生成的质检单号
//			inspection.setOrdersId(qualityInspection.getOrdersId()); // 设置采购单号
//			inspection.setReceiptId(qualityInspection.getReceiptId()); // 设置收货单ID
//
//			if (totalInspectionQuantity > Integer.MAX_VALUE || totalInspectionQuantity < Integer.MIN_VALUE) {
//				throw new ServiceException("总质检量超出Integer类型最大值，转换失败");
//			} else {
//				inspection.setInspectionQuantity(totalInspectionQuantity); // 本次总质检量
//			}
//
//			inspection.setInspector(SecurityUtils.getNickname()); // 设置质检员为当前登录人
//			inspection.setInspectionStatus(QualityCheckStatus.IN_PROGRESS.getCode()); // 设置质检状态为质检中
//			inspection.setDeleteStatus(Constants.INITIALIZE.intValue());
//			inspection.setInspectionDate(new Date());
//			inspection.setCreateTime(new Date());
//			inspection.setUpdateTime(new Date());
//
//			inspectionsToInsert.add(inspection);
//
//			for (DTOReceiptProducts qualityInspectionDatum : qualityInspection.getDtoReceiptProductsList()) {
//				countExpected++;
//
//				// 创建质检单详情
//				List<QualityInspectionDetail> detail = createQualityInspectionDetail(qualityInspectionDatum, inspection.getInspectionId(), productsMap);
//				inspectionDetails.addAll(detail);
//				successCount++;
//
//				List<String> gtins = qualityInspectionDatum.getGtins();
//				if (gtins != null && !gtins.isEmpty() && gtins.size() > 1) {
//					Long inspected = qualityInspectionDatum.getNotInspected(); // 总的质检量（批量质检下总的未质检量就是需要质检的量）
//					for (String gtin : gtins) {
//						// 修改收货详细数据
//						ReceiptProducts products = productsMap.get(qualityInspectionDatum.getReceiptId() + qualityInspectionDatum.getProductId() + gtin); // 从缓存中获取
//						if (products == null) {
//							throw new ServiceException("未找到收货单详细，质检失败！");
//						}
//
//						Integer notInspected = products.getNotInspected(); // 未检量
//						Integer productsQualityInspection = products.getQualityInspection(); // 质检中量
//						// 计算未检量和质检中的量
//						long min = Math.min(notInspected, inspected); // 计算本次扣除的质检量
//						inspected -= min;  // 累减
//						long newNotInspected = notInspected - min; // 计算质检之后的未检量
//						long newQualityInspection = productsQualityInspection + min; // 计算质检完之后的质检中量
//
//						// 在原对象上修改
//						products.setNotInspected((int) newNotInspected); // 更新未质检量
//						products.setQualityStatus(QualityCheckStatus.COMPLETED.getCode()); // 更新质检状态为已完成
//						products.setQualityInspection((int) newQualityInspection); // 更新质检中量
//
//						updatedProducts.add(products);
//					}
//					if (inspected > 0) {
//						throw new ServiceException("质检失败，质检量超出采购量！");
//					}
//				} else {
//					// 修改收货详细数据
//					ReceiptProducts products = productsMap.get(qualityInspectionDatum.getReceiptId() + qualityInspectionDatum.getProductId() + qualityInspectionDatum.getGtin()); // 从缓存中获取
//					if (products == null) {
//						throw new ServiceException("未找到收货单详细，质检失败！");
//					}
//
//					// 计算未检量和质检中的量
//					long notInspected = products.getNotInspected() - qualityInspectionDatum.getNotInspected();
//					if (notInspected < 0) {
//						throw new ServiceException("产品 " + qualityInspectionDatum.getProductName() + " 的未质检量不足，质检失败！");
//					}
//					long inspectionQuantity = products.getQualityInspection() + qualityInspectionDatum.getNotInspected();
//
//					// 在原对象上修改
//					products.setNotInspected((int) notInspected); // 更新未质检量
//					products.setQualityStatus(QualityCheckStatus.COMPLETED.getCode()); // 更新质检状态为已完成
//					products.setQualityInspection((int) inspectionQuantity); // 更新质检中量
//
//					updatedProducts.add(products);
//				}
//			}
//		}
//
//		// 批量插入质检单
//		if (!inspectionsToInsert.isEmpty()) {
//			int inspectionInsertResult = qualityInspectionMapper.insertBatch(inspectionsToInsert); // 自定义批量插入方法
//			if (inspectionInsertResult <= 0) {
//				throw new ServiceException("质检单批量插入失败！");
//			}
//		}
//
//		// 批量插入质检单详情
//		if (!inspectionDetails.isEmpty()) {
//			int detailInsertResult = detailMapper.insertBatch(inspectionDetails);
//			if (detailInsertResult <= 0) {
//				throw new ServiceException("质检单详情批量插入失败！");
//			}
//		}
//
//		// 批量更新 ReceiptProducts
//		if (!updatedProducts.isEmpty()) {
//			int updateResult = receiptProductsMapper.updateBatchByCompositeKey(updatedProducts);
//			if (updateResult <= 0) {
//				throw new ServiceException("收货产品批量更新失败！");
//			}
//		}
//
////		if(true)
////			throw new ServiceException("");
//		return countExpected == successCount ? 1 : 0;
//	}

	/**
	 * 批量新增品检
	 *
	 * @param qualityInspections
	 * @return
	 */
	@Transactional
	@Override
	public int insertBatchQualityInspection(List<Receipt> qualityInspections) {
		// 1. 计算预期插入记录数
		int countExpected = qualityInspections.stream()
				.mapToInt(q -> q.getDtoReceiptProductsList().size())
				.sum();

		// 2. 收集所有 receiptId 和 productId
		Set<String> receiptIds = qualityInspections.stream()
				.flatMap(q -> q.getDtoReceiptProductsList().stream())
				.map(DTOReceiptProducts::getReceiptId)
				.collect(Collectors.toSet());
		Set<Long> productIds = qualityInspections.stream()
				.flatMap(q -> q.getDtoReceiptProductsList().stream())
				.map(DTOReceiptProducts::getProductId)
				.collect(Collectors.toSet());

		// 3. 批量加载 ReceiptProducts 并构建 Map
		Map<String, ReceiptProducts> productsMap = receiptProductsMapper
				.selectByReceiptIdAndProductIdList(receiptIds, productIds)
				.stream()
				.collect(Collectors.toMap(
						item -> item.getReceiptId() + item.getProductId() + item.getGtin(),
						Function.identity()
				));

		// 4. 准备要插入/更新的集合
		List<QualityInspection> inspectionsToInsert = new ArrayList<>(qualityInspections.size());
		List<QualityInspectionDetail> inspectionDetails = new ArrayList<>(countExpected);
		List<ReceiptProducts> updatedProducts = new ArrayList<>(countExpected);

		// 5. 生成质检单号
		List<String> qualityCodes = generateCode(qualityInspections.size());
		Date now = new Date();

		// 6. 主循环：构造质检单与详情，并更新 ReceiptProducts
		for (int i = 0; i < qualityInspections.size(); i++) {
			Receipt receipt = qualityInspections.get(i);
			List<DTOReceiptProducts> productsListDto = receipt.getDtoReceiptProductsList();
			if (productsListDto == null || productsListDto.isEmpty()) {
				throw new IllegalArgumentException("质检数据不能为空或为空集合");
			}

			// 6.1 创建 QualityInspection
			long totalQty = productsListDto.stream()
					.map(DTOReceiptProducts::getReceiptQuantity)
					.filter(Objects::nonNull)
					.filter(qty -> qty != 0)
					.mapToLong(Long::longValue)
					.sum();
			if (totalQty > Integer.MAX_VALUE || totalQty < Integer.MIN_VALUE) {
				throw new ServiceException("总质检量超出Integer类型最大值，转换失败");
			}
			QualityInspection inspection = new QualityInspection();
			inspection.setInspectionId(IdUtils.fastSimpleUUID());
			inspection.setQualityCode(qualityCodes.get(i));
			inspection.setOrdersId(receipt.getOrdersId());
			inspection.setReceiptId(receipt.getReceiptId());
			inspection.setInspectionQuantity(totalQty);
			inspection.setInspector(SecurityUtils.getNickname());
			inspection.setInspectionStatus(QualityCheckStatus.IN_PROGRESS.getCode());
			inspection.setDeleteStatus(Constants.INITIALIZE.intValue());
			inspection.setInspectionDate(now);
			inspection.setCreateTime(now);
			inspection.setUpdateTime(now);
			inspectionsToInsert.add(inspection);

			// 6.2 遍历 DTO 生成详情并更新库存明细
			for (DTOReceiptProducts dto : productsListDto) {
				// 计数
				// successCount 与 countExpected 应保持一致，直接用 countExpected 校验即可

				// 6.2.1 创建质检详情
				inspectionDetails.addAll(
						createQualityInspectionDetail(dto, inspection.getInspectionId(), productsMap)
				);

				// 6.2.2 更新 ReceiptProducts
				updateReceiptProductStatus(dto, productsMap, updatedProducts);
			}
		}

		// 7. 批量持久化
		if (!inspectionsToInsert.isEmpty()) {
			if (qualityInspectionMapper.insertBatch(inspectionsToInsert) <= 0) {
				throw new ServiceException("质检单批量插入失败！");
			}
		}
		if (!inspectionDetails.isEmpty()) {
			if (detailMapper.insertBatch(inspectionDetails) <= 0) {
				throw new ServiceException("质检单详情批量插入失败！");
			}
		}
		if (!updatedProducts.isEmpty()) {
			if (receiptProductsMapper.updateBatchByCompositeKey(updatedProducts) <= 0) {
				throw new ServiceException("收货产品批量更新失败！");
			}
		}

		return 1; // countExpected 与成功记录数逻辑保持不变
	}

	/**
	 * 更新 ReceiptProducts 的未检量、质检中量及状态
	 */
	private void updateReceiptProductStatus(
			DTOReceiptProducts dto,
			Map<String, ReceiptProducts> productsMap,
			List<ReceiptProducts> collector
	) {
		List<String> gtins = dto.getGtins();
		boolean multi = gtins != null && gtins.size() > 1;
		long remaining = dto.getNotInspected();

		if (multi) {
			for (String gtin : gtins) {
				String key = dto.getReceiptId() + dto.getProductId() + gtin;
				ReceiptProducts rp = Optional.ofNullable(productsMap.get(key)).orElseThrow(() -> new ServiceException("未找到收货单详细，质检失败！"));
				int notInspected = rp.getNotInspected();
				int inProgress = rp.getQualityInspection();
				long delta = Math.min(notInspected, remaining);
				remaining -= delta;
				rp.setNotInspected((int) (notInspected - delta));
				rp.setQualityInspection((int) (inProgress + delta));
				rp.setQualityStatus(QualityCheckStatus.COMPLETED.getCode());
				collector.add(rp);
			}
			if (remaining > 0) {
				throw new ServiceException("质检失败，质检量超出采购量！");
			}
		} else {
			String key = dto.getReceiptId() + dto.getProductId() + dto.getGtin();
			ReceiptProducts rp = Optional.ofNullable(productsMap.get(key)).orElseThrow(() -> new ServiceException("未找到收货单详细，质检失败！"));
			long newNotInspected = rp.getNotInspected() - dto.getNotInspected();
			if (newNotInspected < 0) {
				throw new ServiceException("产品 " + dto.getProductName() + " 的未质检量不足，质检失败！");
			}
			rp.setNotInspected((int) newNotInspected);
			rp.setQualityInspection(rp.getQualityInspection() + dto.getNotInspected().intValue());
			rp.setQualityStatus(QualityCheckStatus.COMPLETED.getCode());
			collector.add(rp);
		}
	}

	// 创建质检单详情对象的方法(批量质检时用到的)
	private List<QualityInspectionDetail> createQualityInspectionDetail(DTOReceiptProducts qualityInspectionDatum,
																		String inspectionId,
																		Map<String, ReceiptProducts> productsMap) {

		// 1. 准备 GTIN 列表：多于 1 个就用它，否则用单个默认 GTIN
		List<String> gtins = qualityInspectionDatum.getGtins();
		boolean multi = gtins != null && gtins.size() > 1;
		List<String> gtinList = multi
				? gtins
				: Collections.singletonList(qualityInspectionDatum.getGtin());

		// 2. 检查是否是“免检”（inspectionType == "2"）
		boolean isExemption = "2".equals(qualityInspectionDatum.getInspectionType());

		List<QualityInspectionDetail> details = new ArrayList<>(gtinList.size());
		Date now = new Date();

		// 3. 遍历 GTIN，构造 Detail
		for (String gtin : gtinList) {
			// 3.1 计算质检量和良品量
			int inspectedQty;
			int passQty = 0;

			if (multi) {
				// 多 GTIN：从 productsMap 里取
				String key = qualityInspectionDatum.getReceiptId()
						+ qualityInspectionDatum.getProductId()
						+ gtin;
				ReceiptProducts rp = productsMap.get(key);
				inspectedQty = rp.getNotInspected();
				if (isExemption) {
					passQty = rp.getNotInspected();
				}
			} else {
				// 单 GTIN：直接用 DTO 里的 notInspected
				inspectedQty = qualityInspectionDatum.getNotInspected().intValue();
				if (isExemption) {
					passQty = inspectedQty;
				}
			}

			// 3.2 构造并填充对象
			QualityInspectionDetail detail = new QualityInspectionDetail();
			detail.setDetailId(IdUtils.fastSimpleUUID());
			detail.setInspectionId(inspectionId);
			detail.setProductId(qualityInspectionDatum.getProductId());
			detail.setProductName(qualityInspectionDatum.getProductName());
			detail.setInspectedQuantity(inspectedQty);

			if (isExemption) {
				detail.setInspectionType(QualityCheckMethod.EXEMPTION_CHECK.getCode());
				detail.setPassQuantity(passQty);
			} else {
				detail.setDefectiveQuantity(0);
				detail.setPassQuantity(0);
				detail.setSamplingRatio(BigDecimal.ZERO);
				detail.setSamplingQuantity(0);
				detail.setSamplingPassRate(BigDecimal.ZERO);
			}

			detail.setGtin(gtin);
			detail.setDeleteStatus(Constants.INITIALIZE.intValue());
			detail.setCreatedAt(now);
			detail.setUpdatedAt(now);

			details.add(detail);
		}

		return details;
	}


	public static QualityInspectionVO toQualityInspectionVO(QualityInspection qualityInspection) {
		// 创建目标VO对象
		QualityInspectionVO qualityInspectionVO = new QualityInspectionVO();

		qualityInspectionVO.setOrdersId(String.valueOf(qualityInspection.getOrdersId())); // 将 Long 转为 String

		// 处理 qualityInspectionData 和 inspectionDetails 的映射
		List<QualityInspectionDetail> inspectionDetails = qualityInspection.getQualityInspectionData().stream()
				.map(item -> {
					QualityInspectionDetail detail = new QualityInspectionDetail();
					detail.setInspectedQuantity(item.getCurrentInspectionQuantity().intValue());// 将 currentInspectionQuantity 赋值到 inspectedQuantity
					detail.setProductId(item.getProductId());
					return detail;
				})
				.collect(Collectors.toList());

		qualityInspectionVO.setInspectionDetails(inspectionDetails);

		return qualityInspectionVO;
	}


	/**
	 * 生成防重复提交的唯一key
	 */
	private String generateIdempotentKey(QualityInspection qualityInspection) {
		// 基于用户ID + 订单ID + 数据哈希生成唯一key
		String userId = SecurityUtils.getUserId().toString();
		String ordersId = qualityInspection.getQualityInspectionData().get(0).getOrdersId().toString();
		int dataHash = qualityInspection.getQualityInspectionData().hashCode();

		return String.format("quality_inspection:%s:%s:%d", userId, ordersId, dataHash);
	}

	/**
	 * 新增品检
	 *
	 * @param qualityInspection 品检
	 * @return 结果
	 */
	@Transactional
	@Override
	public int insertQualityInspection(QualityInspection qualityInspection) {

		// 生成防重复提交的key
		String idempotentKey = generateIdempotentKey(qualityInspection);

		// 检查是否重复提交
		if (redisCache.hasKey(idempotentKey)) {
			throw new ServiceException("请勿重复提交，请稍后再试");
		}
		// 设置防重复提交标记，60秒过期
		redisCache.setCacheObject(idempotentKey, "1", 60, TimeUnit.SECONDS);


		try {
			if (qualityInspection.getQualityInspectionData().isEmpty()) {
				throw new IllegalArgumentException("质检数据不能为空或为空集合");
			}

			int countExpected = 0; // 计数器，统计预期插入的记录数
			int successCount = 0; // 计数器，统计成功插入的记录数

			//创建质检单
			String inspectionId = createQualityInspection(qualityInspection.getQualityInspectionData());
			// 判断是否所有产品的质检方式 都为 免检
			boolean allTypeTwo = qualityInspection.getQualityInspectionData().stream()
					.allMatch(product -> product.getInspectionType() != null && product.getInspectionType().equals("2"));

			ProcuredStorage procuredStorage = null; // 入库单id
			if (allTypeTwo) {
				//如果是免检产品则需要创建入库单和入库详细单
				procuredStorage = createStorage(qualityInspection.getQualityInspectionData(), inspectionId);
				updateProcuredOrder(toQualityInspectionVO(qualityInspection));
			}
			//创建质检单详细
			for (DTOReceiptProducts datum : qualityInspection.getQualityInspectionData()) {
				Long currentInspectionQuantity = Optional.ofNullable(datum.getCurrentInspectionQuantity()).orElse(0L);//拿到质检量
				//如果质检量大于0则说明需要创建质检详细单
				if (currentInspectionQuantity > 0) {
					countExpected++; // 增加预期计数
					int insertResult = createQualityInspectionDetails(datum, inspectionId, procuredStorage);
					if (insertResult > 0) {
						successCount++; // 增加成功计数
					}
					// 更新收货单详情
					updateReceiptProductDetails(datum);
				}
			}
			// 比较预期插入数量和实际成功插入数量
			return successCount == countExpected ? 1 : 0;

		} catch (Exception e) {
			// 发生异常时删除防重复提交标记，允许重试
			redisCache.deleteObject(idempotentKey);
			throw e;
		}
	}

	public ProcuredStorage createStorage(List<DTOReceiptProducts> datum, String inspectionId) {
		ProcuredStorage procuredStorage = new ProcuredStorage();
		procuredStorage.setStorageId(IdUtils.fastSimpleUUID());
		procuredStorage.setStorageNumber(generateStorageCode(1).get(0));// 入库单号
		procuredStorage.setInspectionId(inspectionId); // 质检id
		procuredStorage.setOrdersId(datum.get(0).getOrdersId()); // 采购订单id
		procuredStorage.setWarehouseId(datum.get(0).getWarehouseId()); // 预入仓库id
		procuredStorage.setStorageType(StorageTypeEnum.QUALITY_INSPECTION.getCode()); // 入库类型
		procuredStorage.setDepositor(SecurityUtils.getNickname()); // 入库人为当前登录人
		procuredStorage.setInboundStatus(2); //入库状态为已入库
		Integer storageNumber = datum.stream()
				.map(DTOReceiptProducts::getCurrentInspectionQuantity)
				.reduce(0L, Long::sum).intValue();
		procuredStorage.setInboundNumber(storageNumber);//总入库量
		procuredStorage.setTotalPassQuantity(storageNumber);// 总良品量(因为是免检，所以直接将本次免检量都设置为良品量
		procuredStorage.setTotalDefectiveQuantity(Constants.NOT_DELETED_STATUS);// 总次品量（设置为0，因为是免检都是良品没有次品）
		procuredStorage.setInboundTime(new Date()); // 入库时间
		procuredStorage.setAddTime(new Date()); // 添加时间
		procuredStorage.setUpdateTime(new Date()); // 修改时间
		procuredStorage.setDeleteStatus(Constants.NOT_DELETED_STATUS); // 删除状态
		procuredStorageMapper.createStorage(procuredStorage);
		return procuredStorage;
	}

	/**
	 * 创建质检单详细
	 *
	 * @param datum
	 * @return
	 */
	private int createQualityInspectionDetails(DTOReceiptProducts datum, String inspectionId, ProcuredStorage procuredStorage) {
		int currentInspectionQuantity = datum.getCurrentInspectionQuantity().intValue();// 质检数量
		int result = 0; // 受影响行数
		List<String> gtins = datum.getGtins();
		if (gtins != null && !gtins.isEmpty() && gtins.size() > 1) {
			// 构建此质检详细实体类用于更新库存
			QualityInspectionDetail d = new QualityInspectionDetail();
			d.setInspectedQuantity(datum.getCurrentInspectionQuantity().intValue());
			d.setProductName(datum.getProductName());
			d.setProductId(datum.getProductId());
			d.setSku(datum.getSku());
			d.setWarehouseId(datum.getWarehouseId());

			// 说明是一个SKU对应着多个GTIN的情况，需要新增多个质检详细记录
			for (String gtin : datum.getGtins()) {
				// 查询对应的收货单明细查看其收货单明细的分配的未检量是多少
				ReceiptProducts receiptProducts = receiptProductsMapper.selectOne(new LambdaQueryWrapper<ReceiptProducts>()
						.eq(ReceiptProducts::getProductId, datum.getProductId())
						.eq(ReceiptProducts::getDeleteStatus, Constants.NOT_DELETED_STATUS)
						.eq(ReceiptProducts::getGtin, gtin)
						.eq(ReceiptProducts::getReceiptId, datum.getReceiptId()));


				Integer notInspected = receiptProducts.getNotInspected();  // 收货单中未检量
				if (notInspected == 0) {
					continue;
				}
				// 计算可分配的质检数量
				int min = Math.min(currentInspectionQuantity, notInspected);
				currentInspectionQuantity -= min; //扣减对应的质检量

				QualityInspectionDetail detail = new QualityInspectionDetail();
				detail.setDetailId(IdUtils.fastSimpleUUID());
				detail.setInspectionId(inspectionId);//质检id
				detail.setProductId(datum.getProductId());//商品id
				detail.setProductName(datum.getProductName());//商品名称
				detail.setWarehouseId(datum.getWarehouseId());
				detail.setGtin(gtin);
				detail.setSku(datum.getSku());
				detail.setInspectedQuantity(min);// 分配到的质检数量
				detail.setDefectiveQuantity(Constants.NOT_DELETED_STATUS);//次品数量
				if (datum.getInspectionType() != null && datum.getInspectionType().equals("2")) {
					detail.setInspectionType(QualityCheckMethod.EXEMPTION_CHECK.getCode());
					detail.setPassQuantity(min);//良品数量

					// 如果是免检创建入库单详细以及修改对应的采购订单商品的入库数量
					if (procuredStorage != null && procuredStorage.getStorageId() != null) {
						detail.setReceiptProductId(datum.getReceiptProductId());
						createStorageDetails(procuredStorage.getStorageId(), detail);
					}

				} else {
					detail.setPassQuantity(0);//良品数量
					detail.setSamplingRatio(BigDecimal.ZERO);//抽检比例
					detail.setSamplingQuantity(0);//抽检数量
					detail.setSamplingPassRate(BigDecimal.ZERO);//抽检合格率
				}

				detail.setDeleteStatus(Constants.INITIALIZE.intValue());
				detail.setCreatedAt(new Date());
				detail.setUpdatedAt(new Date());
				result += detailMapper.insert(detail);
//				detailsList.add(detail); // 添加到集合中用于后续批量进行插入
				if (datum.getInspectionType() != null && datum.getInspectionType().equals("2")) {
					// 修改采购商品入库数量
					QualityInspectionDetail qualityInspectionDetail = new QualityInspectionDetail();
					qualityInspectionDetail.setDetailId(detail.getDetailId());
					qualityInspectionDetail.setInspectedQuantity(min);
					qualityInspectionDetail.setGtin(gtin);
					updateOrdersProduct(qualityInspectionDetail, true);
				}
				if (currentInspectionQuantity == 0) {
					break;
				}
			}
			// 循环完毕之后如果说还有质检量没有分配完毕，则需要抛出异常提示用户本次质检超出产品的未检量
			if (currentInspectionQuantity > 0) {
				throw new ServiceException("本次质检量超出待检量，请检查!");
			}
			// 入库信息不为空说明用户在收货单处直接进行了免检则直接更新库存
			if (procuredStorage != null && procuredStorage.getStorageId() != null) {
				// 更新库存
				updateInventory(d, procuredStorage);

				// 插入对应的库存入库日志
				processDTOReceiptProducts(datum);
			}
		} else {
			QualityInspectionDetail detail = new QualityInspectionDetail();
			detail.setDetailId(IdUtils.fastSimpleUUID());
			detail.setInspectionId(inspectionId);//质检id
			detail.setProductId(datum.getProductId());//商品id
			detail.setProductName(datum.getProductName());//商品名称
			detail.setWarehouseId(datum.getWarehouseId());
			detail.setSku(datum.getSku());
			detail.setGtin(datum.getGtin());
			detail.setInspectedQuantity(datum.getCurrentInspectionQuantity().intValue());//质检数量
			detail.setDefectiveQuantity(Constants.NOT_DELETED_STATUS);//次品数量
			if (datum.getInspectionType() != null && datum.getInspectionType().equals("2")) {
				detail.setInspectionType(QualityCheckMethod.EXEMPTION_CHECK.getCode());
				detail.setPassQuantity(datum.getCurrentInspectionQuantity().intValue());//良品数量

				// 如果是免检创建入库单详细以及修改对应的采购订单商品的入库数量
				if (procuredStorage != null && procuredStorage.getStorageId() != null) {
					detail.setReceiptProductId(datum.getReceiptProductId());
					createStorageDetails(procuredStorage.getStorageId(), detail);
				}

			} else {
				detail.setPassQuantity(0);//良品数量
				detail.setSamplingRatio(BigDecimal.ZERO);//抽检比例
				detail.setSamplingQuantity(0);//抽检数量
				detail.setSamplingPassRate(BigDecimal.ZERO);//抽检合格率
			}

			detail.setDeleteStatus(Constants.INITIALIZE.intValue());
			detail.setCreatedAt(new Date());
			detail.setUpdatedAt(new Date());
			result += detailMapper.insert(detail);
			if (datum.getInspectionType() != null && datum.getInspectionType().equals("2")) {
				// 修改采购商品入库数量
				QualityInspectionDetail qualityInspectionDetail = new QualityInspectionDetail();
				qualityInspectionDetail.setDetailId(detail.getDetailId());
				qualityInspectionDetail.setInspectedQuantity(datum.getCurrentInspectionQuantity().intValue());
				updateOrdersProduct(qualityInspectionDetail, false);
			}

			if (procuredStorage != null) {
				// 更新库存
				updateInventory(detail, procuredStorage);

				// 插入对应的库存入库日志
				processDTOReceiptProducts(datum);
			}
		}
		return result;
	}

	private void processDTOReceiptProducts(DTOReceiptProducts datum) {
		String sku = datum.getSku();
		Long ordersId = datum.getOrdersId();
		Long productId = datum.getProductId();
		int quantity = datum.getCurrentInspectionQuantity().intValue();
		String remark = datum.getRemark();
		Long warehouseId = datum.getWarehouseId();

		insertInboundStock(sku, ordersId, productId, quantity, remark, warehouseId);
	}


	/**
	 * 创建库存入库日志
	 *
	 * @param sku
	 * @param ordersId
	 * @param productId
	 * @param quantity
	 * @param remark
	 */
	private void insertInboundStock(String sku, Long ordersId, Long productId, int quantity, String remark, Long warehouseId) {
		InboundStock inboundStock = new InboundStock();
		inboundStock.setSku(sku);                         // 产品sku
		inboundStock.setWarehouseId(warehouseId.intValue());// 入库仓库
		inboundStock.setPurchaseOrderId(ordersId);         // 关联的采购订单id
		inboundStock.setQuantity(quantity);              // 入库数量
		inboundStock.setRemainingQuantity(quantity);    // 初始剩余库存量为入库数量
		inboundStock.setRemark(remark);                    // 备注
		inboundStock.setReceivedDate(new Date());          // 入库时间

		// 查询对应的采购成本
		OrdersProduct ordersProduct = ordersProductMapper.selectOne(new LambdaQueryWrapper<OrdersProduct>()
				.eq(OrdersProduct::getOrdersId, ordersId)
				.eq(OrdersProduct::getProductId, productId));

		if (ordersProduct.getTransferableNumber() == null || ordersProduct.getTotalCost() == null) {
			throw new ServiceException("订单数据异常，请联系管理员检查");
		}
		// 判断除数是否为零（如果 ordersProduct.getTransferableNumber() 是数值类型，建议转换为 BigDecimal 后使用 compareTo）
		if (BigDecimal.valueOf(ordersProduct.getTransferableNumber()).compareTo(BigDecimal.ZERO) == 0) {
			throw new ServiceException("采购数量异常，请联系管理员检查");
		}
		// 计算采购单个成本（四舍五入保留四位小数）
		BigDecimal cost = ordersProduct.getTotalCost()
				.divide(BigDecimal.valueOf(ordersProduct.getTransferableNumber()), 6, RoundingMode.HALF_UP);
		inboundStock.setUnitCost(cost);

		// 查询该采购单是否已经存在于日志表中（情况为：采购单被分批次入库了）
		Long count = inboundStockMapper.selectCount(new LambdaQueryWrapper<InboundStock>()
				.eq(InboundStock::getPurchaseOrderId, ordersId.intValue())
				.eq(InboundStock::getSku, sku)
				.eq(InboundStock::getWarehouseId, warehouseId.intValue()));

		if (count > 0) {
			//说明已经存在了，找到同一采购单已经入库过的数据进行修改
			inboundStockMapper.update(null, new LambdaUpdateWrapper<InboundStock>()
					.setSql("remaining_quantity = remaining_quantity + " + quantity)
					.setSql("quantity = quantity + " + quantity)
					.eq(InboundStock::getSku, sku)
					.eq(InboundStock::getPurchaseOrderId, ordersId.intValue())
					.eq(InboundStock::getWarehouseId, warehouseId.intValue()));
		} else {
			//不存在进行新增
			inboundStockMapper.insert(inboundStock);
		}
	}


	/**
	 * 更新收货单详细
	 *
	 * @param datum
	 */
	private void updateReceiptProductDetails(DTOReceiptProducts datum) {
		Long currentInspectionQuantity = datum.getCurrentInspectionQuantity();// 产品本次的质检量
		List<String> gtins = datum.getGtins();
		if (gtins != null && !gtins.isEmpty() && gtins.size() > 1) {
			for (String gtin : datum.getGtins()) {
				// 查询对应的收货单明细查看其收货单明细的分配的未检量是多少
				ReceiptProducts receiptProducts = receiptProductsMapper.selectOne(new LambdaQueryWrapper<ReceiptProducts>()
						.eq(ReceiptProducts::getProductId, datum.getProductId())
						.eq(ReceiptProducts::getDeleteStatus, Constants.NOT_DELETED_STATUS)
						.eq(ReceiptProducts::getGtin, gtin)
						.eq(ReceiptProducts::getReceiptId, datum.getReceiptId()));

				//计算除了质检中的未检量
				long min = Math.min(currentInspectionQuantity, receiptProducts.getNotInspected()); //本次质检量
				if (currentInspectionQuantity == 0) {
					break;
				}
				long notInspected = receiptProducts.getNotInspected() - min;
				currentInspectionQuantity -= min;
				//计算质检中的量
				long inspectionQuantity = receiptProducts.getQualityInspection() + min;

				ReceiptProducts update = new ReceiptProducts();
				update.setGtin(gtin);
				update.setNotInspected((int) notInspected);//更新未质检量


				if (datum.getInspectionType() != null && datum.getInspectionType().equals("2")) {
					// 因为是免检所以直接跳过本次的质检量，不对质检中的量进行计算
					inspectionQuantity -= min;

					//计算免检之后已质检的量
					long checkedQuantity = receiptProducts.getCheckedQuantity() + min;
					update.setCheckedQuantity((int) checkedQuantity);
					//计算免检之后的可用量
					long availableQuantity = receiptProducts.getAvailableQuantity() + min;
					update.setAvailableQuantity((int) availableQuantity);
					if (notInspected == 0 && inspectionQuantity == 0) {
						update.setQualityStatus(QualityCheckStatus.COMPLETED.getCode());  // 质检完成
					} else if (notInspected != 0 && inspectionQuantity == 0) {
						update.setQualityStatus(QualityCheckStatus.PARTIALLY_INSPECTED.getCode());  // 部分质检
					} else {
						// 如果以上两种情况都不是，默认都认为是质检中的状态
						update.setQualityStatus(QualityCheckStatus.IN_PROGRESS.getCode());  // 质检中
					}

				} else {
					update.setQualityStatus(QualityCheckStatus.IN_PROGRESS.getCode());//更新质检状态为质检中
					update.setQualityInspection((int) inspectionQuantity);//更新质检中量
				}

				receiptProductsMapper.update(
						update,
						new LambdaUpdateWrapper<ReceiptProducts>()
								.eq(ReceiptProducts::getReceiptProductId, receiptProducts.getReceiptProductId())
								.eq(ReceiptProducts::getProductId, datum.getProductId())
				);
			}
			if (currentInspectionQuantity > 0) {
				throw new ServiceException("产品" + datum.getProductName() + "的未质检量不足，质检失败！");
			}
		} else {
			//查询收货单详细
			ReceiptProducts products = receiptProductsMapper.selectById(datum.getReceiptProductId());
			//计算除了质检中的未检量
			long notInspected = products.getNotInspected() - datum.getCurrentInspectionQuantity();
			if (notInspected < 0) {
				throw new ServiceException("产品" + datum.getProductName() + "的未质检量不足，质检失败！");
			}
			//计算质检中的量
			long inspectionQuantity = products.getQualityInspection() + datum.getCurrentInspectionQuantity();

			ReceiptProducts update = new ReceiptProducts();
			update.setNotInspected((int) notInspected);//更新未质检量


			if (datum.getInspectionType() != null && datum.getInspectionType().equals("2")) {
				inspectionQuantity -= datum.getCurrentInspectionQuantity();
				//计算免检之后已质检的量
				long checkedQuantity = products.getCheckedQuantity() + datum.getCurrentInspectionQuantity();
				update.setCheckedQuantity((int) checkedQuantity);
				//计算免检之后的可用量
				long availableQuantity = products.getAvailableQuantity() + datum.getCurrentInspectionQuantity();
				update.setAvailableQuantity((int) availableQuantity);
				if (notInspected == 0 && inspectionQuantity == 0) {
					update.setQualityStatus(QualityCheckStatus.COMPLETED.getCode());  // 质检完成
				} else if (notInspected != 0 && inspectionQuantity == 0) {
					update.setQualityStatus(QualityCheckStatus.PARTIALLY_INSPECTED.getCode());  // 部分质检
				} else {
					// 如果以上两种情况都不是，默认都认为是质检中的状态
					update.setQualityStatus(QualityCheckStatus.IN_PROGRESS.getCode());  // 质检中
				}

			} else {
				update.setQualityStatus(QualityCheckStatus.IN_PROGRESS.getCode());//更新质检状态为质检中
				update.setQualityInspection((int) inspectionQuantity);//更新质检中量
			}

			receiptProductsMapper.update(
					update,
					new LambdaUpdateWrapper<ReceiptProducts>()
							.eq(ReceiptProducts::getReceiptProductId, datum.getReceiptProductId())
							.eq(ReceiptProducts::getProductId, datum.getProductId())
			);
		}
	}

	/**
	 * 更新收货单明细，支持多 GTIN
	 */
	private void updateReceiptProductDetailsWithGtin(DTOReceiptProducts datum) {
		List<String> gtins = datum.getGtins();
		if (gtins == null || gtins.isEmpty()) {
			updateReceiptProductDetails(datum); // 保持原逻辑
		} else {
			// 多 GTIN: 更新对应 receipt_products 表中的 GTIN 记录
			for (String gtin : gtins) {
				DTOReceiptProducts dbRp = receiptProductsMapper.selectByReceiptIdAndProductIdAndGTIN(
						datum.getReceiptId(), datum.getProductId(), gtin);
				if (dbRp == null) {
					throw new ServiceException("未找到收货明细，receiptId:" + datum.getReceiptId()
							+ ", productId:" + datum.getProductId() + ", gtin:" + gtin);
				}
				long notInspected = dbRp.getNotInspected() - datum.getCurrentInspectionQuantity();
				if (notInspected < 0) {
					throw new ServiceException("产品" + datum.getProductName() + "的未质检量不足, gtin=" + gtin);
				}
				dbRp.setNotInspected(notInspected);

				// 免检或正常检更新不同字段
				if ("2".equals(datum.getInspectionType())) {
					long checked = dbRp.getCheckedQuantity() + datum.getCurrentInspectionQuantity();
					long avail = dbRp.getAvailableQuantity() + datum.getCurrentInspectionQuantity();
					dbRp.setCheckedQuantity(checked);
					dbRp.setAvailableQuantity(avail);
					// update status...
				} else {
					long qualityInspection = dbRp.getQualityInspection() + datum.getCurrentInspectionQuantity();
					dbRp.setQualityInspection(qualityInspection);
					// update status...
				}
				dbRp.setUpdateTime(new Date());
//				receiptProductsMapper.update(dbRp,
//						new LambdaUpdateWrapper<ReceiptProducts>()
//								.eq(ReceiptProducts::getReceiptProductId, dbRp.getReceiptProductId())
//								.eq(ReceiptProducts::getGtin, gtin));
			}
		}
	}

	/**
	 * 查询某 GTIN 下的未检量
	 */
	private long getNotInspectedForGtin(DTOReceiptProducts datum, String gtin) {
		DTOReceiptProducts prod = receiptProductsMapper.selectByReceiptIdAndProductIdAndGTIN(
				datum.getReceiptId(), datum.getProductId(), gtin);
		return prod == null ? 0L : prod.getNotInspected();
	}

	/**
	 * 创建质检单
	 *
	 * @param datum
	 * @return
	 */
	public String createQualityInspection(List<DTOReceiptProducts> datum) {
		Long totalInspectionQuantity = datum.stream()
				.map(DTOReceiptProducts::getCurrentInspectionQuantity) // 假设这可能返回 null
				.map(quantity -> Optional.ofNullable(quantity).orElse(0L)) // 将 null 转换为 0
				.filter(quantity -> quantity != 0) // 过滤出不为0的值
				.reduce(0L, Long::sum); // 计算总质检量


		QualityInspection inspection = new QualityInspection();
		inspection.setInspectionId(IdUtils.fastSimpleUUID());
		inspection.setQualityCode(generateCode(1).get(0));//质检单号
		inspection.setOrdersId(datum.get(0).getOrdersId()); // 设置采购单号
		inspection.setReceiptId(datum.get(0).getReceiptId()); // 设置收货单id

		if (totalInspectionQuantity > Integer.MAX_VALUE || totalInspectionQuantity < Integer.MIN_VALUE) {
			// 处理超出范围的情况
			throw new ServiceException("总质检量超出Integer类型最大值，转换失败");
		} else {
			inspection.setInspectionQuantity(totalInspectionQuantity);//本次总质检量
		}

		inspection.setInspector(SecurityUtils.getNickname());//设置质检员为当前登录人

		// 判断是否所有产品的质检方式 都为 免检
		boolean allTypeTwo = datum.stream()
				.allMatch(product -> product.getInspectionType() != null && product.getInspectionType().equals("2"));

		inspection.setInspectionStatus(allTypeTwo ? QualityCheckStatus.COMPLETED.getCode() : QualityCheckStatus.IN_PROGRESS.getCode()); // 设置质检状态

		if (allTypeTwo) {
			inspection.setTotalPassQuantity(totalInspectionQuantity);//免检则全是良品
			inspection.setTotalDefectiveQuantity(Constants.INITIALIZE);//次品为0
		}

		inspection.setDeleteStatus(Constants.INITIALIZE.intValue());
		inspection.setInspectionDate(new Date());
		inspection.setCreateTime(new Date());
		inspection.setUpdateTime(new Date());
		qualityInspectionMapper.insertQualityInspection(inspection);

		return inspection.getInspectionId();
	}

	/**
	 * 生成随机数
	 *
	 * @param
	 * @return
	 */
//	private String generateCode() {
//		synchronized (this) {  // 使用同步块，防止多线程并发访问
//			// 获取当前日期
//			SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
//			String currentDate = dateFormat.format(new Date());
//
//			// 获取最后一个质检单编号，在事务中加锁（使用 FOR UPDATE）
//			String lastInspectionNumber = qualityInspectionMapper.selectLastInspectionNumberForUpdate();
//			String number;
//			if (StringUtils.isEmpty(lastInspectionNumber) || !lastInspectionNumber.substring(2, 10).equals(currentDate)) {
//				// 如果没有找到或者日期不匹配，说明是当天的第一个质检单
//				number = Constants.INBOUND_NUMBER;
//			} else {
//				// 提取编号中的序列部分，并加一
//				String lastNumberStr = lastInspectionNumber.substring(10); // 编号格式为：QC + 日期（8位） + 序号（4位）
//				long lastNumber = Long.parseLong(lastNumberStr);
//				number = String.format("%04d", lastNumber + 1);
//			}
//
//			// 拼接生成的代码
//			String code = Constants.INSPECTION_NUMBER + currentDate + number;
//			return code;
//		}
//	}
	private List<String> generateCode(Integer count) {
		synchronized (this) {  // 使用同步块，防止多线程并发访问
			// 获取当前日期
			SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
			String currentDate = dateFormat.format(new Date());

			// 获取最后一个质检单编号，在事务中加锁（使用 FOR UPDATE）
			String lastInspectionNumber = qualityInspectionMapper.selectLastInspectionNumberForUpdate();

			// 生成的编号列表
			List<String> generatedCodes = new ArrayList<>();

			// 如果没有找到最后一个编号，或者日期不匹配，说明是当天的第一个收货单
			String number;
			if (StringUtils.isEmpty(lastInspectionNumber) || !lastInspectionNumber.substring(2, 10).equals(currentDate)) {
				// 如果没有找到或者日期不匹配，生成从CR202411290001开始
				number = Constants.INBOUND_NUMBER;
			} else {
				// 提取编号中的序列部分，并加一
				String lastNumberStr = lastInspectionNumber.substring(10); // 编号格式：CR + 日期（8位） + 序号（4位）
				long lastNumber = Long.parseLong(lastNumberStr);
				number = String.format("%04d", lastNumber + 1);
			}

			// 生成指定数量的编号
			for (int i = 0; i < count; i++) {
				String code = Constants.INSPECTION_NUMBER + currentDate + number;
				// 检查生成的编号是否已存在，避免并发冲突
				int retryCount = 0;
				while (qualityInspectionMapper.checkReceiptNumberExists(code) > 0 && retryCount < 5) {
					// 如果编号已经存在，重新生成
					retryCount++;
					String lastReceiptNumberRetry = qualityInspectionMapper.selectLastInspectionNumberForUpdate();
					if (StringUtils.isEmpty(lastReceiptNumberRetry) || !lastReceiptNumberRetry.substring(2, 10).equals(currentDate)) {
						number = Constants.INBOUND_NUMBER;
					} else {
						String lastNumberStrRetry = lastReceiptNumberRetry.substring(10);
						long lastNumberRetry = Long.parseLong(lastNumberStrRetry);
						number = String.format("%04d", lastNumberRetry + 1);
					}
					code = Constants.INSPECTION_NUMBER + currentDate + number;
				}

				if (retryCount >= 5) {
					// 达到重试次数限制，可以抛出异常或返回失败标志
					throw new RuntimeException("Failed to generate unique receipt number after 5 retries.");
				}

				// 将生成的编号添加到列表
				generatedCodes.add(code);

				// 更新编号的序号
				long currentNumber = Long.parseLong(number);
				number = String.format("%04d", currentNumber + 1);
			}

			return generatedCodes;
		}
	}

	private List<String> generateStorageCode(Integer count) {
		synchronized (this) {  // 使用同步块，防止多线程并发访问
			// 获取当前日期
			SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
			String currentDate = dateFormat.format(new Date());

			// 获取最后一个质检单编号，在事务中加锁（使用 FOR UPDATE）
			String lastInspectionNumber = procuredStorageMapper.selectLastStorageNumberForUpdate();

			// 生成的编号列表
			List<String> generatedCodes = new ArrayList<>();

			// 如果没有找到最后一个编号，或者日期不匹配，说明是当天的第一个收货单
			String number;
			if (StringUtils.isEmpty(lastInspectionNumber) || !lastInspectionNumber.substring(2, 10).equals(currentDate)) {
				// 如果没有找到或者日期不匹配，生成从CR202411290001开始
				number = Constants.INBOUND_NUMBER;
			} else {
				// 提取编号中的序列部分，并加一
				String lastNumberStr = lastInspectionNumber.substring(10); // 编号格式：CR + 日期（8位） + 序号（4位）
				long lastNumber = Long.parseLong(lastNumberStr);
				number = String.format("%04d", lastNumber + 1);
			}

			// 生成指定数量的编号
			for (int i = 0; i < count; i++) {
				String code = Constants.STORAGE_NUMBER + currentDate + number;
				// 检查生成的编号是否已存在，避免并发冲突
				int retryCount = 0;
				while (procuredStorageMapper.checkStorageNumberExists(code) > 0 && retryCount < 5) {
					// 如果编号已经存在，重新生成
					retryCount++;
					String lastStorageNumberRetry = procuredStorageMapper.selectLastStorageNumberForUpdate();
					if (StringUtils.isEmpty(lastStorageNumberRetry) || !lastStorageNumberRetry.substring(2, 10).equals(currentDate)) {
						number = Constants.INBOUND_NUMBER;
					} else {
						String lastNumberStrRetry = lastStorageNumberRetry.substring(10);
						long lastNumberRetry = Long.parseLong(lastNumberStrRetry);
						number = String.format("%04d", lastNumberRetry + 1);
					}
					code = Constants.STORAGE_NUMBER + currentDate + number;
				}

				if (retryCount >= 5) {
					// 达到重试次数限制，可以抛出异常或返回失败标志
					throw new RuntimeException("Failed to generate unique storage number after 5 retries.");
				}


				// 将生成的编号添加到列表
				generatedCodes.add(code);

				// 更新编号的序号
				long currentNumber = Long.parseLong(number);
				number = String.format("%04d", currentNumber + 1);
			}

			return generatedCodes;
		}
	}

	/**
	 * 修改品检
	 *
	 * @param qualityInspection 品检
	 * @return 结果
	 */
	@Transactional
	@Override
	public int updateQualityInspection(QualityInspectionVO qualityInspection) {
		// 基于用户ID + 订单ID + 数据哈希生成唯一key
		String userId = SecurityUtils.getUserId().toString();
		String ordersId = qualityInspection.getOrdersId();
		int dataHash = qualityInspection.getInspectionDetails().hashCode();
		// 生成防重复提交的key
		String idempotentKey = String.format("quality_inspection:%s:%s:%d", userId, ordersId, dataHash);

		// 检查是否重复提交
		if (redisCache.hasKey(idempotentKey)) {
			throw new ServiceException("请勿重复提交，请稍后再试");
		}

		// 设置防重复提交标记，60秒过期
		redisCache.setCacheObject(idempotentKey, "1", 60, TimeUnit.SECONDS);

		try {
			// 修改质检信息
			QualityInspection inspection = new QualityInspection();
			inspection.setInspectionId(qualityInspection.getInspectionId());//更新列
			inspection.setInspector(qualityInspection.getInspector()); // 质检员
			inspection.setInspectionDate(qualityInspection.getInspectionDate()); // 质检时间
			inspection.setUpdateBy(SecurityUtils.getNickname()); // 更新人
			inspection.setInspectionStatus(QualityCheckStatus.COMPLETED.getCode()); // 更新质检状态
			inspection.setUpdateTime(new Date()); // 更新时间
			inspection.setTotalPassQuantity(qualityInspection.getTotalPassQuantity()); // 更新总良品量
			inspection.setTotalDefectiveQuantity(qualityInspection.getTotalDefectiveQuantity()); // 更新总次品量
			//		int totalPassQuantity = 0;//总良品量
			//		int totalDefectiveQuantity = 0;//总次品量

			// 创建入库单
			ProcuredStorage procuredStorage = createWarehouseReceipt(qualityInspection);

			// 更新采购订单的入库状态和入库数量
			updateProcuredOrder(qualityInspection);

			// 更新质检详细信息
			List<QualityInspectionDetail> inspectionDetails = qualityInspection.getInspectionDetails(); // 质检详细信息
			for (QualityInspectionDetail inspectionDetail : inspectionDetails) {
				List<String> gtins = inspectionDetail.getGtins(); // 获取GTIN集合
				if (gtins != null && !gtins.isEmpty() && gtins.size() > 1) {
					Integer totalCount = inspectionDetail.getInspectedQuantity(); // 总质检量
					int totalPassQuantityForSKU = inspectionDetail.getPassQuantity(); // 总良品量
					int totalDefectiveQuantityForSKU = inspectionDetail.getDefectiveQuantity(); // 总次品量

					// 查询对应的质检单明细
					Map<String, QualityInspectionDetail> collect = detailMapper.selectDetails(
									inspectionDetail.getInspectionId(),
									inspectionDetail.getProductId(),
									gtins
							).stream()
							.collect(Collectors.toMap(
									detail -> detail.getGtin() + "-" + detail.getProductId(), // 拼接gtin和productId为键
									detail -> detail // 以QualityInspectionDetail为值
							));

					// 逐一分配每个 GTIN 的良品和次品数量
					for (String gtin : gtins) {
						// 查询出同一SKU对应该GTIN的相关数据
						QualityInspectionDetail detail = collect.get(gtin + '-' + inspectionDetail.getProductId()); // 获取到对应的明细

						Integer inspectedQuantity = detail.getInspectedQuantity();

						if (inspectedQuantity == 0) {
							continue;
						}

						// 对良品量和次品量进行逐一分配
						int passQuantityForGTIN = Math.min(totalPassQuantityForSKU, inspectedQuantity); // 分配良品数量
						totalPassQuantityForSKU -= passQuantityForGTIN; // 剩余待分配的良品量
						int defectiveQuantityForGTIN = Math.min(totalDefectiveQuantityForSKU, inspectedQuantity - passQuantityForGTIN); // 分配次品数量
						totalDefectiveQuantityForSKU -= defectiveQuantityForGTIN; // 剩余待分配的次品量

						// 将分配的数量赋值给 GTIN 相关的质检数据
						detail.setInspectionType(inspectionDetail.getInspectionType()); // 质检方式
						detail.setRemark(inspectionDetail.getRemark());
						detail.setPassQuantity(passQuantityForGTIN);
						detail.setDefectiveQuantity(defectiveQuantityForGTIN);
						detail.setUpdatedAt(new Date()); // 更新时间

						// 将质检方式的代码转换为枚举类型
						QualityCheckMethod inspectionMethod = QualityCheckMethod.fromCode(inspectionDetail.getInspectionType());
//					setCommonDetailFields(detail, inspectionDetail); // 设置公共字段

						// 根据质检方式进行具体赋值
						switch (inspectionMethod) {
							case SAMPLE_CHECK:
								// 抽检需要填写抽检相关数据
								detail.setSamplingRatio(inspectionDetail.getSamplingRatio());
								detail.setSamplingQuantity(inspectionDetail.getSamplingQuantity());
								detail.setSamplingPassRate(inspectionDetail.getSamplingPassRate());
								break;
							case FULL_CHECK:
								// 全检只需填写良品数量和次品数量
								break;
							case EXEMPTION_CHECK:
								// 免检说明质检量全是良品
								inspectionDetail.setPassQuantity(inspectionDetail.getInspectedQuantity());// 将质检数量全部赋值为良品量，方便后面创建入库单时拿数据
								inspectionDetail.setDefectiveQuantity(Constants.NOT_DELETED_STATUS); // 将次品数量赋值为0，方便创建入库单时拿数据
								break;
							default:
								throw new IllegalArgumentException("Invalid inspection type: " + inspectionMethod);
						}

						// 更新质检详细信息
						detailMapper.updateById(detail);

						//创建入库单详细
						createStorageDetails(procuredStorage.getStorageId(), detail);

						// 更新收货商品详细产品质检状态
						updateReceiptProducts(detail);

						// 更新采购订单商品表中的信息
						updateOrdersProduct(detail, true);

						// 插入库存入库日志
						processQualityInspection(inspectionDetail, qualityInspection);

						// 如果良品量和次品量都已分配完，则结束分配
						if (totalPassQuantityForSKU == 0 && totalDefectiveQuantityForSKU == 0) {
							break;
						}
					}
				} else {
					// 初始化质检详细信息对象
					QualityInspectionDetail detail = new QualityInspectionDetail();
					detail.setDetailId(inspectionDetail.getDetailId()); // 更新列
					detail.setInspectionType(inspectionDetail.getInspectionType()); // 质检方式
					detail.setRemark(inspectionDetail.getRemark());
					detail.setUpdatedAt(new Date()); // 更新时间

					// 将质检方式的代码转换为枚举类型
					QualityCheckMethod inspectionMethod = QualityCheckMethod.fromCode(inspectionDetail.getInspectionType());

					switch (inspectionMethod) {
						case SAMPLE_CHECK:
							// 抽检需要填写抽检相关数据
							setCommonDetailFields(detail, inspectionDetail);
							detail.setSamplingRatio(inspectionDetail.getSamplingRatio()); // 抽检比例
							detail.setSamplingQuantity(inspectionDetail.getSamplingQuantity()); // 抽检数量
							detail.setSamplingPassRate(inspectionDetail.getSamplingPassRate()); // 抽检合格率
//						totalPassQuantity += inspectionDetail.getPassQuantity();
//						totalDefectiveQuantity += inspectionDetail.getDefectiveQuantity();
							break;
						case FULL_CHECK:
							// 全检只需填写良品数量和次品数量
							setCommonDetailFields(detail, inspectionDetail);
//						totalPassQuantity += inspectionDetail.getPassQuantity();
//						totalDefectiveQuantity += inspectionDetail.getDefectiveQuantity();
							break;
						case EXEMPTION_CHECK:
							// 免检说明质检量全是良品
							detail.setPassQuantity(inspectionDetail.getInspectedQuantity()); // 良品数量
							inspectionDetail.setPassQuantity(inspectionDetail.getInspectedQuantity());// 将质检数量全部赋值为良品量，方便后面创建入库单时拿数据
							inspectionDetail.setDefectiveQuantity(Constants.NOT_DELETED_STATUS); // 将次品数量赋值为0，方便创建入库单时拿数据
//						totalPassQuantity += inspectionDetail.getInspectedQuantity();
							break;
						default:
							throw new IllegalArgumentException("Invalid inspection type: " + inspectionMethod);
					}

					// 更新质检详细信息
					detailMapper.updateById(detail);
					//创建入库单详细
					createStorageDetails(procuredStorage.getStorageId(), inspectionDetail);

					// 更新收货商品详细产品质检状态
					updateReceiptProducts(inspectionDetail);

					// 更新采购订单商品表中的信息
					updateOrdersProduct(inspectionDetail, false);

					// 插入库存入库日志
					processQualityInspection(inspectionDetail, qualityInspection);
				}
				// 更新库存
				updateInventory(inspectionDetail, procuredStorage);
			}
//		inspection.setTotalPassQuantity((long) totalPassQuantity); // 更新总良品量
//		inspection.setTotalDefectiveQuantity((long) totalDefectiveQuantity); // 更新总次品量
			//更新质检信息
			int result = qualityInspectionMapper.updateQualityInspection(inspection);
			return result;

		} catch (Exception e) {
			// 发生异常时删除防重复提交标记，允许重试
			redisCache.deleteObject(idempotentKey);
			throw e;
		}
	}

	private void processQualityInspection(QualityInspectionDetail inspectionDetail, QualityInspectionVO qualityInspection) {
		String sku = inspectionDetail.getSku();
		Long ordersId = Long.valueOf(qualityInspection.getOrdersId());
		Long productId = inspectionDetail.getProductId();
		int quantity = inspectionDetail.getPassQuantity();
		String remark = inspectionDetail.getRemark();
		Long warehouseId = inspectionDetail.getWarehouseId();

		insertInboundStock(sku, ordersId, productId, quantity, remark, warehouseId);
	}

	// 更新库存
//	private int updateInventory(QualityInspectionDetail inspectionDetail) {
//
//		// 更新库存之前首先查看库存中是否有这个商品
//		LocalInventory inventory = localInventoryMapper.selectProductSku(inspectionDetail.getProductId(),inspectionDetail.getWarehouseId());
//		int result = 0; // 操作标记
//		if(inventory != null){
//			// 说明产品已有库存则进行累加
//			// 1.计算增加后的库存
//			BigDecimal actualQuantity = inventory.getActualQuantity();
//			BigDecimal increasedInventory = actualQuantity.add(new BigDecimal(String.valueOf(inspectionDetail.getInspectedQuantity())));
//
//			inventory.setActualQuantity(increasedInventory);
//			result = localInventoryMapper.updateLocalInventory(inventory);
//
//		}else{
//			// 说明产品没有库存则新增产品库存
//			LocalInventory localInventory = new LocalInventory();
//			localInventory.setInventoryId(IdUtils.fastSimpleUUID());
//			localInventory.setSku(inspectionDetail.getSku()); // 产品sku
//			localInventory.setWarehouseId(inspectionDetail.getWarehouseId()); // 产品仓库
//			localInventory.setActualQuantity(new BigDecimal(inspectionDetail.getInspectedQuantity())); // 初始库存量为本次质检量
//
//			result = localInventoryMapper.insertLocalInventory(localInventory);
//		}
//		return result;
//	}

	private void updateInventory(QualityInspectionDetail inspectionDetail, ProcuredStorage procuredStorage) {
		// 1. 查询并加锁，获取库存信息
		LocalInventory inventory = localInventoryMapper.selectProductSku(inspectionDetail.getProductId(), inspectionDetail.getWarehouseId());

		if (inventory != null) {
			// 2. 使用乐观锁更新库存
			BigDecimal inspectedQty = new BigDecimal(inspectionDetail.getInspectedQuantity());
			BigDecimal previousQty = inventory.getActualQuantity();
			BigDecimal newQty = previousQty.add(inspectedQty);

			int rows = localInventoryMapper.updateLocalInventory(
					inspectionDetail.getProductId(),
					inspectionDetail.getWarehouseId(),
					inventory.getVersion(),
					inspectedQty
			);
			if (rows == 0) {
				// 乐观锁失败，版本不匹配
				throw new ServiceException("库存更新失败，请重试");
			}

			// 3. 插入库存变动明细
			insertInventoryDetails(
					inventory.getInventoryId(),
					inspectionDetail.getSku(),
					inspectionDetail.getWarehouseId(),
					inspectionDetail.getRemark(),
					InventoryChangeType.INBOUND.getCode(),
					inspectedQty,
					previousQty,
					newQty,
					procuredStorage.getStorageNumber()
			);

		} else {
			// 4. 库存记录不存在时，插入新库存
			try {
				LocalInventory newInv = createNewInventory(inspectionDetail);
				localInventoryMapper.insertLocalInventory(newInv); // 插入新库存

				// 5. 插入库存变动明细
				insertInventoryDetails(
						newInv.getInventoryId(),
						inspectionDetail.getSku(),
						inspectionDetail.getWarehouseId(),
						inspectionDetail.getRemark(),
						InventoryChangeType.INBOUND.getCode(),
						new BigDecimal(inspectionDetail.getInspectedQuantity()),
						BigDecimal.ZERO, // 变动前数量为0
						new BigDecimal(inspectionDetail.getInspectedQuantity()), // 变动后数量等于质检数量
						procuredStorage.getStorageNumber()
				);

			} catch (DuplicateKeyException e) {
				// 如果插入失败，可能是并发插入了相同的库存记录
				handleDuplicateKeyError(inspectionDetail, procuredStorage);
			}
		}
	}

	private void insertInventoryDetails(
			String inventoryId,
			String sku,
			Long warehouseId,
			String remark,
			int changeType,
			BigDecimal quantity,
			BigDecimal previousQuantity,
			BigDecimal postChangeQuantity,
			String storageNumber
	) {
		// 这里插入库存变动明细
		LocalInventoryDetails details = new LocalInventoryDetails();
		details.setInventoryDetailId(IdUtils.fastSimpleUUID());
		details.setInventoryId(inventoryId);
		details.setSku(sku);
		details.setWarehouseId(warehouseId);
		details.setOperatorName(SecurityUtils.getNickname()); // 设置操作人为当前操作人
		details.setOperatingTime(new Date()); // 操作时间
		details.setChangeType(changeType); // 变动类型为入库
		details.setQuantity(quantity); // 变动数量
		details.setNotes(remark); // 备注
		details.setPreviousQuantity(previousQuantity); // 变动前的数量
		details.setPostChangeQuantity(postChangeQuantity); // 变动后的数量
		details.setReferenceId(storageNumber); // 关联的入库单
		localInventoryDetailsMapper.insertLocalInventoryDetails(details); // 插入变动记录
	}

	private LocalInventory createNewInventory(QualityInspectionDetail inspectionDetail) {
		LocalInventory newInv = new LocalInventory();
		newInv.setInventoryId(IdUtils.fastSimpleUUID());
		newInv.setSku(inspectionDetail.getSku());
		newInv.setProductId(inspectionDetail.getProductId());
		newInv.setWarehouseId(inspectionDetail.getWarehouseId());
		newInv.setActualQuantity(new BigDecimal(inspectionDetail.getInspectedQuantity()));
		newInv.setReservedQuantity(BigDecimal.ZERO); // 第一次有这个品的库存锁定量默认为0
		newInv.setVersion(0); // 新库存的版本设置为0
		return newInv;
	}

	private void handleDuplicateKeyError(QualityInspectionDetail inspectionDetail, ProcuredStorage procuredStorage) {
		// 重新查询库存数据，防止并发插入
		LocalInventory existing = localInventoryMapper.selectProductSku(inspectionDetail.getProductId(), inspectionDetail.getWarehouseId());
		if (existing != null) {
			BigDecimal inspectedQty = new BigDecimal(inspectionDetail.getInspectedQuantity());
			BigDecimal previousQty = existing.getActualQuantity();
			BigDecimal newQty = previousQty.add(inspectedQty);

			int rows = localInventoryMapper.updateLocalInventory(
					inspectionDetail.getProductId(),
					inspectionDetail.getWarehouseId(),
					existing.getVersion(),
					inspectedQty
			);
			if (rows == 0) {
				throw new ServiceException("并发更新库存失败，请重试");
			}
			// 记录库存变动
			insertInventoryDetails(
					existing.getInventoryId(),
					inspectionDetail.getSku(),
					inspectionDetail.getWarehouseId(),
					inspectionDetail.getRemark(),
					InventoryChangeType.INBOUND.getCode(),
					inspectedQty,
					previousQty,
					newQty,
					procuredStorage.getStorageNumber()
			);
		} else {
			throw new ServiceException("插入库存数据失败，请重试");
		}
	}


	//更新采购订单相关数据
	private void updateProcuredOrder(QualityInspectionVO qualityInspection) {
		ProcuredOrders orders = new ProcuredOrders();
		orders.setOrdersId(Long.valueOf(qualityInspection.getOrdersId()));
		int totalInspectedQuantity = qualityInspection.getInspectionDetails().stream()
				.map(QualityInspectionDetail::getInspectedQuantity) // 映射为 Long 类型的流
				.mapToInt(value -> value != null ? value : 0) // 如果为 null，则用 0 替代
				.sum(); // 计算总和
		// 查询原有采购订单的入库量
		ProcuredOrders procuredOrders = procuredOrdersMapper.selectInboundNumber(qualityInspection.getOrdersId());
		if (procuredOrders.getStatus().equals("4")) {
			// 要是采购订单处于换货中的状态，则需要校验是否需要修改采购订单状态
			// 查询原有订单商品明细
			List<OrdersProduct> list = ordersProductMapper.selectList(new LambdaQueryWrapper<OrdersProduct>()
					.eq(OrdersProduct::getOrdersId, qualityInspection.getOrdersId())
					.eq(OrdersProduct::getDeleteStatus, 0));
			Map<Long, OrdersProduct> collect = list.stream()
					.collect(Collectors.toMap(
							OrdersProduct::getProductId,
							Function.identity(),
							(existing, replacement) -> existing // 处理重复key的策略
					));

			qualityInspection.getInspectionDetails().forEach(
					item -> {
						Integer inspectedQuantity = item.getInspectedQuantity(); // 本次质检数量
						OrdersProduct ordersProducts = collect.get(item.getProductId());
						Integer pendingExchangeQuantity = ordersProducts.getPendingExchangeQuantity();
						if (ordersProducts.getPendingExchangeQuantity() != null) {
							ordersProducts.setPendingExchangeQuantity(ordersProducts.getPendingExchangeQuantity() - inspectedQuantity);
							if (pendingExchangeQuantity - inspectedQuantity == 0) {
								// 查询当前采购单中的所有采购订单明细中是否还有其他明细是否还有待退货量和待换货量
								boolean hasItemWithHighQuantityLowPrice = list.stream()
										.allMatch(product ->
												(product.getPendingExchangeQuantity() == null || product.getPendingExchangeQuantity() <= 0) &&
														(product.getReturnPendingQuantity() == null || product.getReturnPendingQuantity() <= 0)
										);
								if (hasItemWithHighQuantityLowPrice) {
									// 说明采购订单已经没有在进行中的状态了，需要将其设置为已完结
									procuredOrdersMapper.updateStatus(qualityInspection.getOrdersId(), "1");
								}
								int procuredOrderStatus = procuredOrdersMapper.getProcuredOrderStatus(procuredOrders.getOrdersId());
								if (procuredOrderStatus != 4) {
									// 要是查询出来的状态不是换货中则说明有其他状态在审核中等，就需要更新状态
									paymentRequestService.setProcuredOrderStatus(procuredOrders.getOrdersId());
								}
							}
							// 更新待换货量
							ordersProductMapper.updateById(ordersProducts);
						}
					}
			);
		}

		// 计算入库之后的入库数量
		Long inboundNumber = procuredOrders.getInboundNumber();
		int number = inboundNumber.intValue() + totalInspectedQuantity;

		orders.setInboundNumber((long) number);
		if (number > 0 && number >= procuredOrders.getTotal().intValue()) {
			orders.setInboundStatus(Constants.CANCEL_STATUS_ONE); // 已入库
		} else if (number > 0) {
			orders.setInboundStatus(Constants.PAYMENT_STATUS_TWO);// 部分入库
		}
		procuredOrdersMapper.updateInboundStatus(orders);
	}

	// 更新采购订单商品表中的信息
	private void updateOrdersProduct(QualityInspectionDetail inspectionDetail, Boolean flag) {
		OrdersProduct ordersProduct = new OrdersProduct();
		// 获取采购订单号和产品id
		DTOReceiptProducts item = detailMapper.selectOrdersIdAndProductId(inspectionDetail.getDetailId());
		// 如果 item 为 null，直接抛出异常
		if (item == null) {
			throw new ServiceException("修改采购订单时的条件为空，请联系管理员检查！");
		}
		LambdaQueryWrapper<OrdersProduct> eq = new LambdaQueryWrapper<OrdersProduct>()
				.eq(OrdersProduct::getProductId, item.getProductId())
				.eq(OrdersProduct::getOrdersId, item.getOrdersId())
				// 前两个参数是条件，第三个是列，第四个是值
				.eq(item.getGtin() != null, OrdersProduct::getGtin, item.getGtin());

		// 获取原有商品的入库量
		OrdersProduct product = ordersProductMapper.selectOne(eq);

		if (product == null) {
			throw new ServiceException("获取的采购商品信息为空，请联系管理员检查！");
		}
		Long storageNumber = product.getStorageNumber();


		// 获取质检量，先判断是否为 null
		Integer inspectedQuantity = inspectionDetail.getInspectedQuantity();
		if (inspectedQuantity == null) {
			throw new ServiceException("质检量为空，更新采购订单入库量失败！");
		}
		storageNumber += inspectedQuantity;

		// 设置入库量
		ordersProduct.setStorageNumber(storageNumber);

		// 更新操作
		int affectedRows = ordersProductMapper.update(ordersProduct, new LambdaUpdateWrapper<OrdersProduct>()
				.eq(OrdersProduct::getProductId, item.getProductId())
				.eq(OrdersProduct::getOrdersId, item.getOrdersId())
				.eq(flag, OrdersProduct::getGtin, item.getGtin()));

		// 如果没有更新到数据，抛出异常
		if (affectedRows <= 0) {
			throw new ServiceException("更新采购订单入库量失败！没有匹配到记录。");
		}
	}


	//创建入库单详细
	private void createStorageDetails(String storageId, QualityInspectionDetail inspectionDetail) {
		ProcuredStorageDetail detail = new ProcuredStorageDetail();
		detail.setDetailId(IdUtils.fastSimpleUUID());
		detail.setStorageId(storageId);
		detail.setInspectionDetailId(inspectionDetail.getDetailId());
		detail.setProductId(inspectionDetail.getProductId());
		detail.setProductName(inspectionDetail.getProductName());
		detail.setActualQuantity(inspectionDetail.getInspectedQuantity());
		detail.setGoodQuantity(inspectionDetail.getPassQuantity());
		detail.setDefectiveQuantity(inspectionDetail.getDefectiveQuantity());
//		ReceiptProducts products = receiptProductsMapper.selectById(inspectionDetail.getReceiptProductId()); // 查询收货单详细
//		detail.setWaitingQuantity(products.getNotInspected());
		detail.setType(StorageTypeEnum.QUALITY_INSPECTION.getCode());
		detail.setRemark(inspectionDetail.getRemark());
		detail.setGtin(inspectionDetail.getGtin());
		detail.setInboundTime(new Date());
		detail.setAddTime(new Date());
		detail.setUpdateTime(new Date());
		detail.setDeleteStatus(Constants.NOT_DELETED_STATUS);
		procuredStorageDetailMapper.insert(detail);
	}

	//创建入库单
	public ProcuredStorage createWarehouseReceipt(QualityInspectionVO qualityInspection) {
		ProcuredStorage procuredStorage = new ProcuredStorage();
		procuredStorage.setStorageId(IdUtils.fastSimpleUUID());
		procuredStorage.setStorageNumber(generateStorageCode(1).get(0));// 入库单号
		procuredStorage.setInspectionId(qualityInspection.getInspectionId()); // 质检id
		procuredStorage.setOrdersId(Long.valueOf(qualityInspection.getOrdersId())); // 采购订单id
		procuredStorage.setWarehouseId(qualityInspection.getWarehouseId()); // 预入仓库id
		procuredStorage.setStorageType(StorageTypeEnum.QUALITY_INSPECTION.getCode()); // 入库类型
		procuredStorage.setDepositor(SecurityUtils.getNickname()); // 入库人为当前登录人
		procuredStorage.setInboundStatus(2); //入库状态为已入库
		procuredStorage.setInboundNumber(qualityInspection.getInspectionQuantity().intValue());//总入库量
		procuredStorage.setTotalPassQuantity(qualityInspection.getTotalPassQuantity().intValue());// 总良品量
		procuredStorage.setTotalDefectiveQuantity(qualityInspection.getTotalDefectiveQuantity().intValue());// 总次品量
		procuredStorage.setInboundTime(new Date()); // 入库时间
		procuredStorage.setAddTime(new Date()); // 添加时间
		procuredStorage.setUpdateTime(new Date()); // 修改时间
		procuredStorage.setDeleteStatus(Constants.NOT_DELETED_STATUS); // 删除状态
		procuredStorageMapper.createStorage(procuredStorage);
		return procuredStorage;
	}

	// 提取的公共方法，用于设置次品数量和良品数量
	private void setCommonDetailFields(QualityInspectionDetail detail, QualityInspectionDetail inspectionDetail) {
		detail.setDefectiveQuantity(inspectionDetail.getDefectiveQuantity()); // 次品数量
		detail.setPassQuantity(inspectionDetail.getPassQuantity()); // 良品数量
	}

	// 提取的公共方法，用于更新收货商品信息
	private void updateReceiptProducts(QualityInspectionDetail inspectionDetail) {
		// 查询收货单详细
		ReceiptProducts products = receiptProductsMapper.selectById(inspectionDetail.getReceiptProductId());

		// 初始化收货商品对象
		ReceiptProducts receiptProducts = new ReceiptProducts();
		receiptProducts.setReceiptProductId(inspectionDetail.getReceiptProductId()); // 更新主键列

		// 计算质检完之后的质检中量
		int remainingQualityInspection = products.getQualityInspection() - inspectionDetail.getInspectedQuantity();
		receiptProducts.setQualityInspection(remainingQualityInspection);

		// 更新已质检量
		int totalCheckedQuantity = products.getCheckedQuantity() + inspectionDetail.getInspectedQuantity();
		receiptProducts.setCheckedQuantity(totalCheckedQuantity);

		// 更新可用量和次品量
		int availableQuantity = products.getAvailableQuantity();
		int defectiveQuantity = products.getDefectiveQuantity();

		// 将质检方式的代码转换为枚举类型
		QualityCheckMethod inspectionMethod = QualityCheckMethod.fromCode(inspectionDetail.getInspectionType());

		if (inspectionMethod == QualityCheckMethod.EXEMPTION_CHECK) {
			// 免检情况
			availableQuantity += inspectionDetail.getInspectedQuantity();
		} else {
			// 全检和抽检情况
			availableQuantity += inspectionDetail.getPassQuantity();
			defectiveQuantity += inspectionDetail.getDefectiveQuantity();
		}
		// 更新质检状态
		if (products.getNotInspected() == 0 && remainingQualityInspection == 0) {
			// 质检完成
			receiptProducts.setQualityStatus(QualityCheckStatus.COMPLETED.getCode());
		} else if (products.getNotInspected() != 0 && remainingQualityInspection == 0) {
			// 部分质检
			receiptProducts.setQualityStatus(QualityCheckStatus.PARTIALLY_INSPECTED.getCode());
		} else {
			// 质检中（包括：已经开始质检但是未完成，或者质检进行中）
			receiptProducts.setQualityStatus(QualityCheckStatus.IN_PROGRESS.getCode());
		}

		receiptProducts.setAvailableQuantity(availableQuantity);
		receiptProducts.setDefectiveQuantity(defectiveQuantity);
		receiptProducts.setUpdateTime(new Date());
		receiptProductsMapper.updateById(receiptProducts);
	}


	/**
	 * 批量删除品检
	 *
	 * @param inspectionIds 需要删除的品检主键
	 * @return 结果
	 */
	@Transactional
	@Override
	public int deleteQualityInspectionByInspectionIds(String[] inspectionIds) {
		if (inspectionIds == null || inspectionIds.length == 0) {
			return 0;
		}


		// 1. 获取所有需要删除的质检单，包括收货单ID
		List<QualityInspection> inspectionsToDelete = qualityInspectionMapper.selectList(inspectionIds);

		if (inspectionsToDelete.isEmpty()) {
			return 0;
		}

		boolean hasCompleted = inspectionsToDelete.stream()
				.anyMatch(ins ->
						// 假设 getInspectionStatus() 返回的是 int 或 Integer
						Objects.equals(ins.getInspectionStatus(), QualityCheckStatus.COMPLETED.getCode())
				);

		if (hasCompleted) {
			throw new ServiceException("该质检单已质检，请刷新页面！");
		}

		// 2. 获取所有需要删除的质检单详细，包含产品ID和质检数量等
		List<QualityInspectionDetail> inspectionDetailsToDelete = detailMapper.selectList(
				new LambdaQueryWrapper<QualityInspectionDetail>()
						.in(QualityInspectionDetail::getInspectionId, Arrays.asList(inspectionIds))
						.eq(QualityInspectionDetail::getDeleteStatus, Constants.NOT_DELETED_STATUS)
		);

		// 3. 组装收货单ID和产品ID的映射，以便后续更新收货单详细
		Map<String, List<QualityInspectionDetail>> receiptIdToInspectionDetailsMap = new HashMap<>();
		for (QualityInspection inspection : inspectionsToDelete) {
			String receiptId = inspection.getReceiptId();
			if (receiptId == null) {
				continue; // 如果没有对应的收货单ID，跳过
			}

			// 获取当前质检单对应的质检详细
			List<QualityInspectionDetail> details = inspectionDetailsToDelete.stream()
					.filter(detail -> detail.getInspectionId().equals(inspection.getInspectionId()))
					.collect(Collectors.toList());

//			if (!details.isEmpty()) {
//				receiptIdToInspectionDetailsMap.put(receiptId, details);
//			}

			if (!details.isEmpty()) {
				// 使用 computeIfAbsent 方法，如果 key 不存在则创建新的列表
				receiptIdToInspectionDetailsMap.computeIfAbsent(receiptId, k -> new ArrayList<>()).addAll(details);
			}
		}

		// 4. 根据收货单ID和产品ID，更新收货单详细的数据
		for (Map.Entry<String, List<QualityInspectionDetail>> entry : receiptIdToInspectionDetailsMap.entrySet()) {
			String receiptId = entry.getKey();//收货单id
			List<QualityInspectionDetail> details = entry.getValue();//对应的质检详细数据

			// 获取当前收货单的所有收货单详细
			List<ReceiptProducts> receiptDetails = receiptProductsMapper.selectList(
					new LambdaQueryWrapper<ReceiptProducts>()
							.eq(ReceiptProducts::getReceiptId, receiptId)
							.in(ReceiptProducts::getProductId, details.stream()
									.map(QualityInspectionDetail::getProductId)
									.collect(Collectors.toSet()))
			);

			// 以产品ID为键，收货单详细为值的映射
			Map<String, ReceiptProducts> productIdToReceiptDetailMap = receiptDetails.stream()
					.collect(Collectors.toMap(item -> item.getProductId() + '-' + item.getGtin(), Function.identity()));

			// 更新收货单详细的数据
			for (QualityInspectionDetail detail : details) {
				Long productId = detail.getProductId();
				String gtin = detail.getGtin();
				ReceiptProducts receiptDetail = productIdToReceiptDetailMap.get(productId.intValue() + '-' + gtin);
				if (receiptDetail != null) {
					if (detail.getInspectionType() != null && detail.getInspectionType().equals(QualityCheckMethod.EXEMPTION_CHECK.getCode())) {
						//如果是免检的话则还需要将已检量和可用量进行回滚
						int checkedQuantity = receiptDetail.getCheckedQuantity() - detail.getInspectedQuantity();
						receiptDetail.setCheckedQuantity(checkedQuantity);//更新已检量
						int availableQuantity = receiptDetail.getAvailableQuantity() - detail.getInspectedQuantity();
						receiptDetail.setAvailableQuantity(availableQuantity);
					}
					// 回滚收货单详细中的质检中量和未检量
					int inspectedQuantity = receiptDetail.getQualityInspection() - detail.getInspectedQuantity();//更新之后的质检中量
					int notInspected = receiptDetail.getNotInspected() + detail.getInspectedQuantity();//更新之后的未检量
					receiptDetail.setQualityInspection(inspectedQuantity);
					receiptDetail.setNotInspected(notInspected);

					// 质检中
					if (notInspected != 0 && inspectedQuantity != 0) {
						receiptDetail.setQualityStatus(QualityCheckStatus.IN_PROGRESS.getCode());
					}
					// 部分质检完成
					else if (notInspected != 0 && receiptDetail.getCheckedQuantity() != 0) {
						receiptDetail.setQualityStatus(QualityCheckStatus.PARTIALLY_INSPECTED.getCode());
					}
					// 未质检
					else if (inspectedQuantity == 0 && receiptDetail.getCheckedQuantity() == 0) {
						receiptDetail.setQualityStatus(QualityCheckStatus.NOT_INSPECTED.getCode());
					}

					// 更新收货单详细记录
					receiptProductsMapper.updateById(receiptDetail);
				}
			}
		}

		// 5. 删除质检单详细
		if (!inspectionDetailsToDelete.isEmpty()) {
			List<String> detailIds = inspectionDetailsToDelete.stream()
					.map(QualityInspectionDetail::getDetailId)
					.collect(Collectors.toList());
			detailMapper.deleteBatchIds(detailIds);
		}

		// 6. 删除质检单
		int result = qualityInspectionMapper.deleteQualityInspectionByInspectionIds(inspectionIds);
//		if(true){
//			throw new ServiceException("");
//		}

		return result;
	}


	/**
	 * 删除品检信息
	 *
	 * @param inspectionId 品检主键
	 * @return 结果
	 */
	@Override
	public int deleteQualityInspectionByInspectionId(Long inspectionId) {
		return qualityInspectionMapper.deleteQualityInspectionByInspectionId(inspectionId);
	}

	/**
	 * 根据产品id查询库存次品量详细
	 *
	 * @param vo
	 * @return
	 */
	@Override
	public List<QualityInspectionDetailVO> selectQualityInspectionByProductId(QualityInspectionDetailVO vo) {
		if (vo.getProductId() == null) {
			throw new ServiceException("缺少查询参数产品id！");
		}

		List<QualityInspectionDetailVO> list = detailMapper.selectQualityInspectionByProductId(vo);
		// 提取 productIds
		List<Long> productIds = list.stream()
				.map(QualityInspectionDetailVO::getProductId)
				.collect(Collectors.toList());


		if (productIds.isEmpty() || list.isEmpty()) {
			return new ArrayList<>();
		}


		Map<Integer, List<String>> collect = productImageMapper.selectProductImagesByProductId(productIds)
				.stream()
				.collect(Collectors.groupingBy(ProductImage::getProductId,
						Collectors.mapping(ProductImage::getProductImagePath, Collectors.toList())));


		list.forEach(item -> {
			List<String> imagePath = collect.getOrDefault(item.getProductId().intValue(), new ArrayList<>());
			item.setProductImagePath(imagePath);
		});
		return list;
	}
}
